﻿Imports System.Drawing.Graphics
Imports System.Drawing.Drawing2D

Public Class dmnCalender2
    Private m_TimeSlotCollection As TimeSlotCollection
    Private m_EventsCollection As New EventCollection
    Private _MouseDown As Boolean = False
    Private _Start As Int16 = 0
    Private _End As Int16 = 0
    Private _Zoom As enmZoomMode = enmZoomMode.Hour

    Enum enmZoomMode
        'Year
        'Month
        Week
        Hour_6
        Hour_4
        Hour
        HalfHour
        Min_15
    End Enum

    Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        'm_TimeSlotCollection.Canvas = picCanvas
        For Each zoom As dmnCalender2.enmZoomMode In [Enum].GetValues(GetType(dmnCalender2.enmZoomMode))
            comZoom.Items.Add(zoom)
        Next
        DrawBackGround()
    End Sub

    Private Sub DrawBackGround()
        m_TimeSlotCollection = New TimeSlotCollection
        Dim lSlots As Integer = 24
        Dim lDays As Integer = 1
        Dim lMinPerSlot As Integer = 60
        If _Zoom = enmZoomMode.Hour Then
            lSlots = 24
            lMinPerSlot = 60
        ElseIf _Zoom = enmZoomMode.HalfHour Then
            lSlots = 48
            lMinPerSlot = 30
        ElseIf _Zoom = enmZoomMode.Min_15 Then
            lSlots = 96
            lMinPerSlot = 15
        ElseIf _Zoom = enmZoomMode.Hour_4 Then
            lSlots = 6
            lMinPerSlot = 240
        ElseIf _Zoom = enmZoomMode.Hour_6 Then
            lSlots = 4
            lMinPerSlot = 360
        ElseIf _Zoom = enmZoomMode.Week Then
            lSlots = 24
            lMinPerSlot = 60
            lDays = 7
        Else
            lSlots = 1
            lMinPerSlot = 1440
        End If
        For lDay As Integer = 1 To lDays
            Dim dtCurrentDate As Date = dtPickerDate.Value
            Dim lTop As Integer = 22
            Dim lSlotTime As Date = FormatDateTime(dtCurrentDate, DateFormat.ShortDate) & " 00:00"
            'Dim lHeader As clsHeader = m_TimeSlotCollection.AddHeader((picCanvas.Width / lDays) * (lDay - 1), _
            '                                                      lTop, 22, _
            '                                                      picCanvas.Width / lDays)
            'lHeader.StartTime = dtCurrentDate
            For iSlot As Integer = 1 To lSlots
                Dim lTs As clsTimeSlot = m_TimeSlotCollection.Add((picCanvas.Width / lDays) * (lDay - 1), _
                                                                  lTop, 22, _
                                                                  picCanvas.Width / lDays)
                If lDay > 1 Then
                    lTs.MainLeft = (lDay - 1) * (picCanvas.Width / lDays)
                Else
                    lTs.MainLeft = 0
                End If

                lTs.Index = iSlot
                lTs.StartTime = lSlotTime
                lTs.Text = Format(lTs.StartTime, "HH:mm")
                lSlotTime = DateAdd(DateInterval.Minute, lMinPerSlot, lSlotTime)
                lTop = 22 * iSlot
            Next
            dtCurrentDate.AddDays(1)
        Next
        pnlMain.Refresh()
        pnlMain.VerticalScroll.Value = 0
        pnlMain.VerticalScroll.Minimum = 0
        pnlMain.VerticalScroll.Maximum = lSlots
        picCanvas.Top = 0
        picCanvas.Height = lSlots * 22

        m_TimeSlotCollection.Canvas = picCanvas
        m_TimeSlotCollection.Draw()
        'For Each ts As lTimeSlot In m_TimeSlotCollection
        '    If ts.WorkingHour Then
        '        'picCanvas.Top = ts.Top * -1
        '        pnlMain.VerticalScroll.Value = ts.Index * -1
        '        pnlMain.Refresh()
        '        Exit For
        '    End If
        'Next
    End Sub

    Private Sub pnlMain_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles pnlMain.Resize
        picCanvas.Left = 0
        picCanvas.Width = pnlMain.Width - 20
        picCanvas.Top = 0
        pnlMain.Refresh()
        DrawBackGround()
        pnlMain.AutoScroll = True
    End Sub

    Private Sub picCanvas_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picCanvas.MouseDown
        _MouseDown = True
        _Start = e.Y
        picCanvas_MouseMove(sender, e)
    End Sub

    Private Sub picCanvas_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picCanvas.MouseMove
        If _MouseDown Then
            For Each ts As clsTimeSlot In m_TimeSlotCollection
                If (e.Y >= ts.Top) And (e.Y <= (ts.Top + ts.Height)) Then
                    ts.Marked = True
                End If
            Next
            m_TimeSlotCollection.Draw()
        End If
    End Sub

    Private Sub picCanvas_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picCanvas.MouseUp
        _MouseDown = False
        _End = e.Y
        Dim strMarked As String = String.Empty
        Dim lStartTime As DateTime = Date.MinValue
        Dim lDuration As Integer = 0
        For Each ts As clsTimeSlot In m_TimeSlotCollection
            If ts.Marked Then
                If lStartTime = Date.MinValue Then
                    lStartTime = ts.StartTime
                    lDuration += ts.Duration
                End If
                strMarked &= ts.Text & ";"
                ts.Marked = False
            End If
        Next
        m_EventsCollection.Add(strMarked, lStartTime, lDuration)
        MessageBox.Show("Marked " & strMarked)

        m_TimeSlotCollection.Draw()

    End Sub

    Private Sub comZoom_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles comZoom.SelectedValueChanged
        _Zoom = comZoom.SelectedItem
        DrawBackGround()
    End Sub
End Class

Friend Class EventCollection
    Inherits CollectionBase

    Public Function Add() As clsEvent
        Return Add("", Date.MinValue, 0)
    End Function

    Public Function Add(ByVal pText As String, _
                        ByVal pStartTime As Date, _
                        ByVal pDuration As Integer) As clsEvent
        Dim lEvent As New clsEvent
        lEvent.Text = pText
        lEvent.StartTime = pStartTime
        lEvent.Duration = pDuration
        Me.List.Add(lEvent)
        Return lEvent
    End Function

End Class

Friend Class clsEvent
    Private _Text As String = String.Empty
    Private _StartTime As Date = Date.MinValue
    Private _Duration As Integer = 0

    Public Property Text() As String
        Get
            Return _Text
        End Get
        Set(ByVal value As String)
            _Text = value
        End Set
    End Property
    Public Property StartTime() As Date
        Get
            Return _StartTime
        End Get
        Set(ByVal value As Date)
            _StartTime = value
        End Set
    End Property

    Property Duration() As Integer
        Get
            Return _Duration
        End Get
        Set(ByVal value As Integer)
            _Duration = value
        End Set
    End Property

End Class

Friend Class TimeSlotCollection
    Inherits CollectionBase
    Private _MyCanvas As PictureBox
    Private _WorkingHoursColour As Brush = Brushes.Wheat
    Private _NonWorkingHoursColour As Brush = Brushes.LightGray
    Private _StartWorkingHour As Date = FormatDateTime(Date.Now, DateFormat.ShortDate) & " 7:00"
    Private _EndWorkingHour As Date = FormatDateTime(Date.Now, DateFormat.ShortDate) & " 17:00"

    Property Canvas() As PictureBox
        Get
            Return _MyCanvas
        End Get
        Set(ByVal value As PictureBox)
            _MyCanvas = value
        End Set
    End Property

    Public Function Add()
        Return Add(0, 0, 0, 0)
    End Function

    Public Function AddHeader(ByVal pLeft As Integer, ByVal pTop As Integer, ByVal pHeight As Integer, ByVal pWidth As Integer) As clsHeader
        Dim lHeader As New clsHeader
        lHeader.Left = pLeft
        lHeader.Top = pTop
        lHeader.Height = pHeight
        lHeader.Width = pWidth
        'Me.List.Add(lHeader)
        Return lHeader
    End Function

    Public Function Add(ByVal pLeft As Integer, ByVal pTop As Integer, ByVal pHeight As Integer, ByVal pWidth As Integer) As clsTimeSlot
        Dim lTimeSlot As New clsTimeSlot
        lTimeSlot.Left = pLeft
        lTimeSlot.Top = pTop
        lTimeSlot.Height = pHeight
        lTimeSlot.Width = pWidth
        Me.List.Add(lTimeSlot)
        Return lTimeSlot
    End Function

    Public Sub Draw()
        If _MyCanvas IsNot Nothing Then
            Dim pic As PictureBox = CType(_MyCanvas, PictureBox)
            Dim fnt As System.Drawing.Font = New Font("Arial", 10, FontStyle.Regular)
            pic.BackgroundImage = Nothing
            If IsNothing(pic.BackgroundImage) Then
                pic.BackgroundImage = New Bitmap(_MyCanvas.Width, _MyCanvas.Height)
            End If
            Dim g As Graphics = Graphics.FromImage(pic.BackgroundImage)
            'Draw Header
            
            For Each ts As clsTimeSlot In Me
                Dim brsh As Brush
                If ts.Index = 1 Then
                    Dim rectHeader As New Rectangle(ts.MainLeft, 0, Me(0).Width, Me(0).Height)
                    Dim lPenHeader As Pen = New Pen(Color.Black, 0.5)
                    brsh = Brushes.Coral
                    g.FillRectangle(brsh, rectHeader)
                    g.DrawRectangle(lPenHeader, rectHeader)
                    g.DrawString(ts.StartTime.ToString, fnt, Brushes.Black, ts.MainLeft, ts.Top)
                End If

                If (ts.StartTime >= _StartWorkingHour) And (ts.StartTime < _EndWorkingHour) Then
                    brsh = _WorkingHoursColour
                    ts.WorkingHour = True
                Else
                    brsh = _NonWorkingHoursColour
                    ts.WorkingHour = False
                End If
                Dim rect As New Rectangle(ts.MainLeft, ts.Top, ts.Width, ts.Height)
                Dim lPen As Pen = New Pen(Color.Black, 0.5)
                If ts.Marked Then
                    brsh = Brushes.AliceBlue
                    g.FillRectangle(brsh, rect)
                    g.DrawRectangle(lPen, rect)
                Else
                    g.FillRectangle(brsh, rect)
                    g.DrawRectangle(lPen, rect)
                End If
                g.DrawString(ts.Text, fnt, Brushes.Black, ts.MainLeft, ts.Top)
            Next
        End If
    End Sub
End Class

Friend Class clsTimeSlot
    Private _Left As Integer = 0
    Private _Top As Integer = 0
    Private _Height As Integer = 0
    Private _Width As Integer = 0
    Private _Text As String = ""
    Private _Marked As Boolean = False
    Private _StartTime As Date
    Private _Duration As Integer
    Private _WorkingHour As Boolean = False
    Private _Index As Integer = 0

    Private _MainLeft As Integer = 0
    'Private _Date As DateTime = Date.Now

    'Property SlotDate() As DateTime
    '    Get
    '        Return _Date
    '    End Get
    '    Set(ByVal value As DateTime)
    '        _Date = value
    '    End Set
    'End Property

    Property MainLeft() As Integer
        Get
            Return _MainLeft
        End Get
        Set(ByVal value As Integer)
            _MainLeft = value
        End Set
    End Property

    Property Index() As Integer
        Get
            Return _Index
        End Get
        Set(ByVal value As Integer)
            _Index = value
        End Set
    End Property

    Property WorkingHour() As Boolean
        Get
            Return _WorkingHour
        End Get
        Set(ByVal value As Boolean)
            _WorkingHour = value
        End Set
    End Property

    Property StartTime() As Date
        Get
            Return _StartTime
        End Get
        Set(ByVal value As Date)
            _StartTime = value
        End Set
    End Property

    Property Duration() As Integer
        Get
            Return _Duration
        End Get
        Set(ByVal value As Integer)
            _Duration = value
        End Set
    End Property
    Property Marked() As Boolean
        Get
            Return _Marked
        End Get
        Set(ByVal value As Boolean)
            _Marked = value
        End Set
    End Property
    Property Text() As String
        Get
            Return _Text
        End Get
        Set(ByVal value As String)
            _Text = value
        End Set
    End Property
    Property Left() As Integer
        Get
            Return _Left
        End Get
        Set(ByVal value As Integer)
            _Left = value
        End Set
    End Property

    Property Top() As Integer
        Get
            Return _Top
        End Get
        Set(ByVal value As Integer)
            _Top = value
        End Set
    End Property

    Property Height() As Integer
        Get
            Return _Height
        End Get
        Set(ByVal value As Integer)
            _Height = value
        End Set
    End Property

    Property Width() As Integer
        Get
            Return _Width
        End Get
        Set(ByVal value As Integer)
            _Width = value
        End Set
    End Property
End Class

Friend Class clsHeader
    Private _Left As Integer = 0
    Private _Top As Integer = 0
    Private _Height As Integer = 0
    Private _Width As Integer = 0
    Private _Text As String = ""
    Private _Marked As Boolean = False
    Private _StartTime As Date
    Private _Duration As Integer
    Private _WorkingHour As Boolean = False
    Private _Index As Integer = 0

    Property Index() As Integer
        Get
            Return _Index
        End Get
        Set(ByVal value As Integer)
            _Index = value
        End Set
    End Property

    Property WorkingHour() As Boolean
        Get
            Return _WorkingHour
        End Get
        Set(ByVal value As Boolean)
            _WorkingHour = value
        End Set
    End Property

    Property StartTime() As Date
        Get
            Return _StartTime
        End Get
        Set(ByVal value As Date)
            _StartTime = value
        End Set
    End Property

    Property Duration() As Integer
        Get
            Return _Duration
        End Get
        Set(ByVal value As Integer)
            _Duration = value
        End Set
    End Property
    Property Marked() As Boolean
        Get
            Return _Marked
        End Get
        Set(ByVal value As Boolean)
            _Marked = value
        End Set
    End Property
    Property Text() As String
        Get
            Return _Text
        End Get
        Set(ByVal value As String)
            _Text = value
        End Set
    End Property
    Property Left() As Integer
        Get
            Return _Left
        End Get
        Set(ByVal value As Integer)
            _Left = value
        End Set
    End Property

    Property Top() As Integer
        Get
            Return _Top
        End Get
        Set(ByVal value As Integer)
            _Top = value
        End Set
    End Property

    Property Height() As Integer
        Get
            Return _Height
        End Get
        Set(ByVal value As Integer)
            _Height = value
        End Set
    End Property

    Property Width() As Integer
        Get
            Return _Width
        End Get
        Set(ByVal value As Integer)
            _Width = value
        End Set
    End Property
End Class